package gis.web.demo;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.NotImplementedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import gis.algorithm.GeoPie;
import gis.algorithm.GeoPoint;
import gis.algorithm.GeoUtils;
import gis.algorithm.Legend;
import gis.algorithm.RenderMethod;
import gis.algorithm.tide.RqTide;
import gis.algorithm.tide.TideArg;
import gis.algorithm.tide.TideCalculator;
import gis.algorithm.tide.TileGrid;
import gis.algtest.BizCell;
import gis.algtest.BizService;

/**
 *
 */
@Controller("Service_Tide")
@RequestMapping({"/service/tide"})
public class Tide {
    private static Logger logger = LoggerFactory.getLogger(Tide.class);
    private static TileGrid tideGrid102100 = null;
    private static TileGrid tideGrid4326 = null;

    /**
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        RqTide rq;

        try {
            int x = Integer.parseInt(request.getParameter("x"));
            int y = Integer.parseInt(request.getParameter("y"));
            int z = Integer.parseInt(request.getParameter("z"));
            int wkid = Integer.parseInt(request.getParameter("wkid"));
            double resolution = Double.parseDouble(request.getParameter("r"));
            double originX = Double.parseDouble(request.getParameter("ox"));
            double originY = Double.parseDouble(request.getParameter("oy"));

            rq = new RqTide();
            rq.setX(x);
            rq.setY(y);
            rq.setZ(z);
            rq.setWkid(wkid);
            rq.setResolution(resolution);
            rq.setOriginX(originX);
            rq.setOriginY(originY);
        } catch (Exception e) {
            logger.debug(e.getMessage(), e);
            Output(response, null);
            return;
        }

        // 构造请求图片的左上角地理坐标
        GeoPoint leftTopPoint = GeoUtils.getLeftTopPoint(rq.getOriginX(),rq.getOriginY(), rq.getResolution(), rq.getX(), rq.getY());

        // 全地图的网格数据
        TileGrid grid = getGrid(rq);
        List<Legend> legends = getLegends();

        TideCalculator calc = TideCalculator.getInstance();
        BufferedImage image = calc.createColorImage(rq.getResolution(), grid, leftTopPoint,legends, 256);
        Output(response, image);
    }

    /**
     * @param rq
     * @return
     */
    private synchronized TileGrid getGrid(RqTide rq) {
        int wkid = rq.getWkid();
        if (wkid == 102100) {
            if (tideGrid102100 == null) {
                List<TideArg> args = getArgs(rq);
                logger.debug("Initializing 102100 grid ...");
                TideCalculator calc = TideCalculator.getInstance();
                tideGrid102100 = calc.createTileGrid(args, 200);
                logger.debug("Initializing 102100 grid complate");
            }
            return tideGrid102100;
        } else if (wkid == 4326) {
            if (tideGrid4326 == null) {
                List<TideArg> args = getArgs(rq);
                logger.debug("Initializing 4326 grid ...");
                TideCalculator calc = TideCalculator.getInstance();
                tideGrid4326 = calc.createTileGrid(args, 0.002);
                logger.debug("Initializing 4326 grid complate");
            }
            return tideGrid4326;
        } else {
            throw new NotImplementedException(String.valueOf(wkid));
        }
    }

    /**
     * 获取密度图算法基础数据
     *
     * @param rq
     * @return
     */
    private List<TideArg> getArgs(RqTide rq) {
        List<TideArg> args = new ArrayList<TideArg>();
        BizCell[] cells = BizService.getInstance().getCells();
        int wkid = rq.getWkid();

        for (int i = 0; i < cells.length; i++) {
            BizCell cell = cells[i];
            double lon = cell.getLongitude();
            double lat = cell.getLatitude();

            GeoPoint point;
            if (wkid == 4326) {
                point = new GeoPoint(lon, lat);
            } else if (wkid == 102100) {
                point = GeoUtils.lonLatToMercator(lon, lat);
            } else {
                throw new NotImplementedException(String.valueOf(wkid));
            }

            // 构造扇形对象
            int radius = cell.getCoverRadius();
            double startAngle = cell.getAntennaAzimuth() - cell.getAntbw();
            double sweepAngle = cell.getAntbw() * 2;
            GeoPie pie = new GeoPie(point, radius, startAngle, sweepAngle, wkid);

            TideArg arg = new TideArg();
            //arg.setAntbw(cell.getAntbw());
            //arg.setAntennaAzimuth(cell.getAntennaAzimuth());
            //arg.setCoverRadius(cell.getCoverRadius());
            arg.setArea(pie.getArea());
            arg.setLatitude(point.getY());
            arg.setLongitude(point.getX());
            arg.setRenderMethod(RenderMethod.Sum);
            arg.setRingExtent(pie.getRingExtent());
            arg.setRingPoints(pie.getRingPoints());
            arg.setValue(cell.getTchTraf());
            args.add(arg);
        }

        return args;
    }

    /**
     * 获取当前图例设置
     *
     * @return
     */
    private List<Legend> getLegends() {
        List<Legend> legends = new ArrayList<Legend>();

        Legend legend0 = new Legend();
        legend0.setColor(Color.WHITE);
        legend0.setValue(-20);
        legend0.setText(String.valueOf(legend0.getValue()));
        legends.add(legend0);

        Legend legend1 = new Legend();
        legend1.setColor(Color.GREEN);
        legend1.setValue(200);
        legend1.setText(String.valueOf(legend1.getValue()));
        legends.add(legend1);

        Legend legend2 = new Legend();
        legend2.setColor(Color.YELLOW);
        legend2.setValue(400);
        legend2.setText(String.valueOf(legend2.getValue()));
        legends.add(legend2);

        Legend legend3 = new Legend();
        legend3.setColor(Color.RED);
        legend3.setValue(600);
        legend3.setText(String.valueOf(legend3.getValue()));
        legends.add(legend3);

        return legends;
    }

    /**
     * @param response
     * @param image
     */
    private void Output(HttpServletResponse response, BufferedImage image) {
        response.setContentType("image/png");
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setDateHeader("expires", -1);

        if (image != null) {
            ServletOutputStream output;
            try {
                output = response.getOutputStream();
                ImageIO.write(image, "png", output);
                output.close();
            } catch (IOException e) {
            }
        }
    }
}
